再战朋友圈

朋友圈从开始前前后后经历了几次改造,前天晚上决定还是换一种方式。原因如下:部分友链网站更新并不及时,个别已经一年未更新,并且朋友圈前台速度我也一直不满意,趁这次修改,把解析友链网站RSS的逻辑也变更了一下。

新逻辑如下:解析单个友链网站前5篇文章,一旦获取成功,该站解析进程立刻终止。并且这5篇文章只保留网站名称、站标、文章标题、文章链接及发布(更新)日期,其它项目及5篇文章以后的全部删除,依然保存在rsscache目录下。待所有网站获取成功后,按照发布(更新)日期进行排序,一旦数量达到30篇,所有流程结束,后面的文章全部忽略,以卡片的形式只显示前30篇。

这样的好处是,以前都是解析所有友链网站的整个rss文件,少则几十KB,多则二百多KB,现在都在5KB以内。尽管前台显示速度还是没有达到我要的效果,不过比之前算是有了质的飞跃。

再战朋友圈-似水流年

改造后的代码如下:

一、如果你的PHP安装的有redis扩展,使用如下代码。(非常推荐)

[reply]

<?php
/*
Template Name: 似水流年-RSS 朋友圈
*/

// 设置时区
date_default_timezone_set('America/New_York'); 
// 获取页面头部信息
get_header(); 
// 引入 SimplePie 类
require_once(ABSPATH. WPINC. '/class-simplepie.php');

// 输出页面主内容区域的 HTML 部分
echo '<div id="primary" class="content-area">';
echo '<main id="main" class="site-main" role="main">';
echo '<p style="color: red; font-size: 14px; margin-top: 10px; margin-bottom: 20px; text-align: center; display: flex; align-items: center; justify-content: center;">以下友情链接网站最新内容每 2 小时获取更新一次</p>';

// 定义缓存更新时间间隔
$cache_update_interval = 2 * 3600;

// 验证 URL 合法性
function is_valid_url($url) {
    return filter_var($url, FILTER_VALIDATE_URL)!== false;
}

// 连接 Redis 服务器
function connect_redis() {
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    return $redis;
}

// 检查 Redis 中是否存在缓存且未过期
function is_redis_cache_valid($redis, $key, $cache_update_interval) {
    $last_update = $redis->get($key. ':last_update');
    if ($last_update) {
        return (time() - $last_update < $cache_update_interval);
    }
    return false;
}

// 存储 RSS 数据到 Redis
function store_rss_in_redis($redis, $key, $rss_content) {
    $redis->set($key, $rss_content);
    $redis->set($key. ':last_update', time());
}

// 处理单个链接的 RSS 数据
function process_single_link_rss_data($link, $cache_update_interval) {
    // 检查 URL 合法性和解析域名
    if (!is_valid_url($link->link_url) ||!is_valid_url($link->link_rss)) {
        return [];
    }
    $domain = parse_url($link->link_url, PHP_URL_HOST);
    if (!$domain) {
        return [];
    }
    $redis = connect_redis();
    $key ='rsscache:'. $domain;
    $site_articles = [];
    $count_site_articles = 0;
    // 检查 Redis 缓存是否需要更新
    if (is_redis_cache_valid($redis, $key, $cache_update_interval)) {
        $rss_content = $redis->get($key);
        $rss = new SimplePie();
        $rss->set_raw_data($rss_content);
        $rss->init();
        $rss_items = $rss->get_items();
        foreach ($rss_items as $item) {
            if ($count_site_articles >= 5) {
                break;
            }
            $item_data = array(
                'link_name' => $link->link_name,
                'link_logo' => $link->link_image,
                'link_url' => $link->link_url,
                'item_title' => $item->get_title(),
                'item_link' => $item->get_permalink(),
                'item_date' => $item->get_date('Y-m-d H:i:s'),
                'formatted_date' => date('Y-m-d', strtotime($item->get_date('Y-m-d H:i:s'))),
                'item_author' => $item->get_author()->get_name(),
                'item_excerpt' => $item->get_description(),
                'item_content' => strip_tags($item->get_content(), '<p><br>'), 
            );
            $site_articles[] = $item_data;
            $count_site_articles++;
        }
        return $site_articles;
    }
    // 获取并处理 RSS 内容
    $rss_content = get_rss_content($link->link_rss);
    if ($rss_content && $rss_content!= '无法从提供 RSS 的 URL 获取 RSS 内容。') {
        $processed_rss_content = process_rss_content($rss_content);
        store_rss_in_redis($redis, $key, $processed_rss_content);
        $rss = new SimplePie();
        $rss->set_raw_data($processed_rss_content);
        $rss->init();
        $rss_items = $rss->get_items();
        foreach ($rss_items as $item) {
            if ($count_site_articles >= 5) {
                break;
            }
            $item_data = array(
                'link_name' => $link->link_name,
                'link_logo' => $link->link_image,
                'link_url' => $link->link_url,
                'item_title' => $item->get_title(),
                'item_link' => $item->get_permalink(),
                'item_date' => $item->get_date('Y-m-d H:i:s'),
                'formatted_date' => date('Y-m-d', strtotime($item->get_date('Y-m-d H:i:s'))),
                'item_author' => $item->get_author()->get_name(),
                'item_excerpt' => $item->get_description(),
                'item_content' => strip_tags($item->get_content(), '<p><br>'), 
            );
            $site_articles[] = $item_data;
            $count_site_articles++;
        }
    }
    return $site_articles;
}

// 获取并缓存友情链接的 RSS 数据
function get_cached_friend_link_rss_data($cache_update_interval) {
    $all_articles = [];
    $links = get_bookmarks(array(
        'orderby' => 'name',
        'category' => 0,
        'order' => 'ASC',
        'hide_invisible' => 1,
        'categorize' => 0,
        'title_li' => '',
        'echo' => 0
    ));
    foreach ($links as $link) {
        if ($link->link_rss &&!empty($link->link_rss)) {
            $site_articles = process_single_link_rss_data($link, $cache_update_interval);
            $all_articles = array_merge($all_articles, $site_articles);
        }
    }
    return $all_articles;
}

// 获取 RSS 内容
function get_rss_content($feed_url) {
    $response = wp_safe_remote_get($feed_url, array('sslverify' => true));
    if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) {
        return wp_remote_retrieve_body($response);
    } else {
        $response = wp_safe_remote_get($feed_url, array('sslverify' => false));
        if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) {
            return wp_remote_retrieve_body($response);
        } else {
            error_log("无法从提供 RSS 的 URL: {$feed_url} 获取 RSS 内容,错误信息: ". print_r( $response, true));
            return '无法从提供 RSS 的 URL 获取 RSS 内容。';
        }
    }
}

// 处理 RSS 内容
function process_rss_content($rss_content) {
    $dom = new DOMDocument();
    // 清除可能存在的 BOM 头
    $rss_content = preg_replace('/^\xEF\xBB\xBF/', '', $rss_content);
    // 去除多余的空格和换行符
    $rss_content = trim($rss_content);
    // 尝试加载 XML 内容
    if ($dom->loadXML($rss_content)) {
        $items = $dom->getElementsByTagName('item');
        $channel = $dom->getElementsByTagName('channel')->item(0);
        // 处理前 5 个 <item> 元素
        for ($i = 0; $i < min(5, $items->length); $i++) {
            $item = $items->item($i);
            $categoryNodes = $item->getElementsByTagName('category');
            foreach ($categoryNodes as $categoryNode) {
                while ($categoryNode->hasChildNodes()) {
                    $categoryNode->removeChild($categoryNode->firstChild);
                }
            }
            $descriptionNodes = $item->getElementsByTagName('description');
            foreach ($descriptionNodes as $descriptionNode) {
                while ($descriptionNode->hasChildNodes()) {
                    $descriptionNode->removeChild($descriptionNode->firstChild);
                }
            }
            $contentEncodedNodes = $item->getElementsByTagNameNS('http://purl.org/rss/1.0/modules/content/', 'encoded');
            foreach ($contentEncodedNodes as $contentEncodedNode) {
                while ($contentEncodedNode->hasChildNodes()) {
                    $contentEncodedNode->removeChild($contentEncodedNode->firstChild);
                }
            }
        }
        // 删除第 5 个 <item> 元素后的内容
        $countItemEndTags = 0;
        $childNodes = $channel->childNodes;
        $removeStartIndex = -1;
        for ($i = 0; $i < $childNodes->length; $i++) {
            $node = $childNodes->item($i);
            if ($node->nodeName == 'item') {
                $countItemEndTags++;
                if ($countItemEndTags == 5) {
                    $removeStartIndex = $i + 1;
                }
            }
        }
        if ($removeStartIndex!= -1) {
            $fragment = $dom->createDocumentFragment();
            for ($i = 0; $i < $removeStartIndex; $i++) {
                $fragment->appendChild($childNodes->item($i)->cloneNode(true));
            }
            for ($i = $removeStartIndex; $i < $childNodes->length; $i++) {
                $node = $childNodes->item($i);
                if ($node->nodeName == 'channel') {
                    $fragment->appendChild($node->cloneNode(true));
                    break;
                }
            }
            while ($channel->hasChildNodes()) {
                $channel->removeChild($channel->firstChild);
            }
            $channel->appendChild($fragment);
        }
        return $dom->saveXML();
    } else {
        // 处理加载 XML 失败的情况
        error_log("Failed to load XML content from RSS feed.");
        return '';
    }
}


// 获取最新的 30 篇友情链接文章
function get_latest_friend_link_articles($cache_update_interval) {
    $latest_articles = get_cached_friend_link_rss_data($cache_update_interval);
    usort($latest_articles, function($a, $b) {
        $dateA = new DateTime($a['item_date']);
        $dateB = new DateTime($b['item_date']);
        return $dateB <=> $dateA;
    });
    $sorted_articles = array_slice($latest_articles, 0, 30);
    return $sorted_articles;
}

// 获取并显示友情链接的最新文章
$cache_update_interval = 2 * 3600; // 2 小时
$latest_articles = get_latest_friend_link_articles($cache_update_interval);
?>
<div class="row">
    <?php foreach ($latest_articles as $article) {
?>
    <div class="col-sm-4">
        <div class="card" style="background-color: white; border-radius: 10px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); margin-bottom: 15px;">
            <div class="card-body" style="display: flex; flex-direction: column; height: 100%;">
                <div style="flex: 4; display: flex;">
                    <div style="flex: 4; padding: 5px; overflow: hidden; display: flex; align-items: center;">
                        <a href="<?php echo esc_url($article['item_link']);?>" target="_blank" style="font-size: 14px;"><?php echo esc_html($article['item_title']);?></a>
                    </div>
                    <div style="flex: 1; padding: 5px; display: flex; justify-content: center; align-items: center;">
                        <img src="<?php echo esc_url($article['link_logo']);?>" alt="<?php echo esc_attr($article['link_name']);?> Logo" style="width: 100%; height: 100%; object-fit: contain;">
                    </div>
                </div>
                <div style="flex: 1; display: flex;">
                    <div style="flex: 1; padding: 5px; display: flex; align-items: center;">
                        <a href="<?php echo esc_url($article['link_url']);?>" target="_blank" style="font-size: 14px;"><?php echo esc_html($article['link_name']);?></a>
                    </div>
                    <div style="flex: 1; padding: 5px; display: flex; justify-content: flex-end; align-items: center;">
                        <span style="font-size: 14px;"><?php echo esc_html($article['formatted_date']);?></span>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <?php }?>
</div>
<?php
// 获取并显示侧边栏
get_sidebar(); 
echo '</main><!-- #main -->';
echo '</div><!-- #primary -->';
// 获取并显示页面底部信息
get_footer(); 
?>

[/reply]

二、如果你的PHP没有安装redis扩展,使用以下代码。

[reply]

<?php
/*
Template Name: 似水流年-RSS 朋友圈
*/

// 设置时区
date_default_timezone_set('America/New_York'); 
// 获取页面头部信息
get_header(); 
// 引入 SimplePie 类
require_once(ABSPATH. WPINC. '/class-simplepie.php');

// 输出页面主内容区域的 HTML 部分
echo '<div id="primary" class="content-area">';
echo '<main id="main" class="site-main" role="main">';
echo '<p style="color: red; font-size: 14px; margin-top: 10px; margin-bottom: 20px; text-align: center; display: flex; align-items: center; justify-content: center;">以下友情链接网站最新内容每 2 小时获取更新一次</p>';

// 定义缓存更新时间间隔
$cache_update_interval = 2 * 3600;

// 验证 URL 合法性
function is_valid_url($url) {
    return filter_var($url, FILTER_VALIDATE_URL)!== false;
}

// 处理单个链接的 RSS 数据
function process_single_link_rss_data($link, $cache_update_interval) {
    // 检查 URL 合法性和解析域名
    if (!is_valid_url($link->link_url) ||!is_valid_url($link->link_rss)) {
        return [];
    }
    $domain = parse_url($link->link_url, PHP_URL_HOST);
    if (!$domain) {
        return [];
    }
    $cache_file = get_stylesheet_directory(). '/rsscache/'. $domain. '.xml';
    $site_articles = [];
    $count_site_articles = 0;
    // 检查缓存是否需要更新
    if (file_exists($cache_file)) {
        $rss_items = get_rss_items($cache_file);
        $latest_item_date = null;
        foreach ($rss_items as $item) {
            $date = new DateTime($item->get_date('Y-m-d H:i:s'));
            $date->setTimezone(new DateTimeZone('America/New_York')); 
            $item_date = $date->getTimestamp();
            if ($latest_item_date === null || $item_date > $latest_item_date) {
                $latest_item_date = $item_date;
            }
        }
        if ($latest_item_date!== null && (time() - $latest_item_date < $cache_update_interval) ) {
            // 从缓存中获取文章信息
            foreach ($rss_items as $item) {
                if ($count_site_articles >= 5) {
                    break;
                }
                $item_data = array(
                    'link_name' => $link->link_name,
                    'link_logo' => $link->link_image,
                    'link_url' => $link->link_url,
                    'item_title' => $item->get_title(),
                    'item_link' => $item->get_permalink(),
                    'item_date' => $item->get_date('Y-m-d H:i:s'),
                    'formatted_date' => date('Y-m-d', strtotime($item->get_date('Y-m-d H:i:s'))),
                    'item_author' => $item->get_author()->get_name(),
                    'item_excerpt' => $item->get_description(),
                    'item_content' => strip_tags($item->get_content(), '<p><br>'), 
                );
                $site_articles[] = $item_data;
                $count_site_articles++;
            }
            return $site_articles;
        }
    }
    // 获取并处理 RSS 内容
    $rss_content = get_rss_content($link->link_rss);
    if ($rss_content && $rss_content!= '无法从提供 RSS 的 URL 获取 RSS 内容。') {
        $processed_rss_content = process_rss_content($rss_content);
        // 确保目录存在
        if (!is_dir(dirname($cache_file))) {
            mkdir(dirname($cache_file), 0755, true);
        }
        file_put_contents($cache_file, $processed_rss_content);
        $rss_items = get_rss_items($cache_file);
        foreach ($rss_items as $item) {
            if ($count_site_articles >= 5) {
                break;
            }
            $item_data = array(
                'link_name' => $link->link_name,
                'link_logo' => $link->link_image,
                'link_url' => $link->link_url,
                'item_title' => $item->get_title(),
                'item_link' => $item->get_permalink(),
                'item_date' => $item->get_date('Y-m-d H:i:s'),
                'formatted_date' => date('Y-m-d', strtotime($item->get_date('Y-m-d H:i:s'))),
                'item_author' => $item->get_author()->get_name(),
                'item_excerpt' => $item->get_description(),
                'item_content' => strip_tags($item->get_content(), '<p><br>'), 
            );
            $site_articles[] = $item_data;
            $count_site_articles++;
        }
    }
    return $site_articles;
}

// 获取并缓存友情链接的 RSS 数据
function get_cached_friend_link_rss_data($cache_update_interval) {
    $all_articles = [];
    $links = get_bookmarks(array(
        'orderby' => 'name',
        'category' => 0,
        'order' => 'ASC',
        'hide_invisible' => 1,
        'categorize' => 0,
        'title_li' => '',
        'echo' => 0
    ));
    foreach ($links as $link) {
        if ($link->link_rss &&!empty($link->link_rss)) {
            $site_articles = process_single_link_rss_data($link, $cache_update_interval);
            $all_articles = array_merge($all_articles, $site_articles);
        }
    }
    return $all_articles;
}

// 获取 RSS 内容
function get_rss_content($feed_url) {
    $response = wp_safe_remote_get($feed_url, array('sslverify' => true));
    if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) {
        return wp_remote_retrieve_body($response);
    } else {
        $response = wp_safe_remote_get($feed_url, array('sslverify' => false));
        if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) {
            return wp_remote_retrieve_body($response);
        } else {
            error_log("无法从提供 RSS 的 URL: {$feed_url} 获取 RSS 内容,错误信息: ". print_r( $response, true));
            return '无法从提供 RSS 的 URL 获取 RSS 内容。';
        }
    }
}

// 处理 RSS 内容
function process_rss_content($rss_content) {
    $dom = new DOMDocument();
    // 清除可能存在的 BOM 头
    $rss_content = preg_replace('/^\xEF\xBB\xBF/', '', $rss_content);
    // 去除多余的空格和换行符
    $rss_content = trim($rss_content);
    // 尝试加载 XML 内容
    if ($dom->loadXML($rss_content)) {
        $items = $dom->getElementsByTagName('item');
        $channel = $dom->getElementsByTagName('channel')->item(0);
        // 处理前 5 个 <item> 元素
        for ($i = 0; $i < min(5, $items->length); $i++) {
            $item = $items->item($i);
            $categoryNodes = $item->getElementsByTagName('category');
            foreach ($categoryNodes as $categoryNode) {
                while ($categoryNode->hasChildNodes()) {
                    $categoryNode->removeChild($categoryNode->firstChild);
                }
            }
            $descriptionNodes = $item->getElementsByTagName('description');
            foreach ($descriptionNodes as $descriptionNode) {
                while ($descriptionNode->hasChildNodes()) {
                    $descriptionNode->removeChild($descriptionNode->firstChild);
                }
            }
            $contentEncodedNodes = $item->getElementsByTagNameNS('http://purl.org/rss/1.0/modules/content/', 'encoded');
            foreach ($contentEncodedNodes as $contentEncodedNode) {
                while ($contentEncodedNode->hasChildNodes()) {
                    $contentEncodedNode->removeChild($contentEncodedNode->firstChild);
                }
            }
        }
        // 删除第 5 个 <item> 元素后的内容
        $countItemEndTags = 0;
        $childNodes = $channel->childNodes;
        $removeStartIndex = -1;
        for ($i = 0; $i < $childNodes->length; $i++) {
            $node = $childNodes->item($i);
            if ($node->nodeName == 'item') {
                $countItemEndTags++;
                if ($countItemEndTags == 5) {
                    $removeStartIndex = $i + 1;
                }
            }
        }
        if ($removeStartIndex!= -1) {
            $fragment = $dom->createDocumentFragment();
            for ($i = 0; $i < $removeStartIndex; $i++) {
                $fragment->appendChild($childNodes->item($i)->cloneNode(true));
            }
            for ($i = $removeStartIndex; $i < $childNodes->length; $i++) {
                $node = $childNodes->item($i);
                if ($node->nodeName == 'channel') {
                    $fragment->appendChild($node->cloneNode(true));
                    break;
                }
            }
            while ($channel->hasChildNodes()) {
                $channel->removeChild($channel->firstChild);
            }
            $channel->appendChild($fragment);
        }
        return $dom->saveXML();
    } else {
        // 处理加载 XML 失败的情况
        error_log("Failed to load XML content from RSS feed.");
        return '';
    }
}

// 使用 SimplePie 获取 RSS 项
function get_rss_items($cache_file) {
    $rss = new SimplePie();
    $rss->set_feed_url($cache_file);
    $rss->init();
    $rss->handle_content_type();
    $rss->set_output_encoding('UTF-8');
    return $rss->get_items();
}

// 获取最新的 30 篇友情链接文章
function get_latest_friend_link_articles($cache_update_interval) {
    $latest_articles = get_cached_friend_link_rss_data($cache_update_interval);
    usort($latest_articles, function($a, $b) {
        $dateA = new DateTime($a['item_date']);
        $dateB = new DateTime($b['item_date']);
        return $dateB <=> $dateA;
    });
    $sorted_articles = array_slice($latest_articles, 0, 30);
    return $sorted_articles;
}

// 获取并显示友情链接的最新文章
$latest_articles = get_latest_friend_link_articles($cache_update_interval);
?>
<div class="row">
    <?php foreach ($latest_articles as $article) {
?>
    <div class="col-sm-4">
        <div class="card" style="background-color: white; border-radius: 10px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); margin-bottom: 15px;">
            <div class="card-body" style="display: flex; flex-direction: column; height: 100%;">
                <div style="flex: 4; display: flex;">
                    <div style="flex: 4; padding: 5px; overflow: hidden; display: flex; align-items: center;">
                        <a href="<?php echo esc_url($article['item_link']);?>" target="_blank" style="font-size: 14px;"><?php echo esc_html($article['item_title']);?></a>
                    </div>
                    <div style="flex: 1; padding: 5px; display: flex; justify-content: center; align-items: center;">
                        <img src="<?php echo esc_url($article['link_logo']);?>" alt="<?php echo esc_attr($article['link_name']);?> Logo" style="width: 100%; height: 100%; object-fit: contain;">
                    </div>
                </div>
                <div style="flex: 1; display: flex;">
                    <div style="flex: 1; padding: 5px; display: flex; align-items: center;">
                        <a href="<?php echo esc_url($article['link_url']);?>" target="_blank" style="font-size: 14px;"><?php echo esc_html($article['link_name']);?></a>
                    </div>
                    <div style="flex: 1; padding: 5px; display: flex; justify-content: flex-end; align-items: center;">
                        <span style="font-size: 14px;"><?php echo esc_html($article['formatted_date']);?></span>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <?php }?>
</div>
<?php
// 获取并显示侧边栏
get_sidebar(); 
echo '</main><!-- #main -->';
echo '</div><!-- #primary -->';
// 获取并显示页面底部信息
get_footer(); 
?>

[/reply]

Comments | 11 条评论
  • 扶苏

    Microsoft Edge 131 Microsoft Edge 131 Windows 10 Windows 10 1美国 ip address 2604:9cc0:13:46f:*:*

    我来瞅一瞅最新版

  • 沉沦

    Google Chrome 131 Google Chrome 131 Mac OS X 10.15 Mac OS X 10.15 1中国–河北 电信 ip address 27.128.*.*

    你的站就不提供全文摘要,所以我就通过 p 标签来提取全文,然而你边栏也有 p 标签包裹的文字:Luohe,Henan打工仔Worker 所以你的文章每篇前面都带有这个😂

    • 似水流年

      Microsoft Edge 131 Microsoft Edge 131 Windows 10 Windows 10 1中国–河南–漯河 联通 ip address 182.126.*.*

      确实要缩小P标签的范围。

  • 沉沦

    Google Chrome 131 Google Chrome 131 Mac OS X 10.15 Mac OS X 10.15 1中国–河北 电信 ip address 27.128.*.*

    现在这个效果不错啊,我一直在犹豫还要不要保留摘要...主要是有的博客并不提供全文摘要,有的文章可能就一句话就没了...造成摘要截断行数不足四行。如果通过 css 过滤器获取完文的话,获取的全文格式又五花八门还要再次过滤,真的是人都麻了~

    • 似水流年

      Microsoft Edge 131 Microsoft Edge 131 Windows 10 Windows 10 1中国–河南–漯河 联通 ip address 182.126.*.*

      这就是我去掉摘要的原因。

  • 刘郎

    Google Chrome 127 Google Chrome 127 GNU/Linux GNU/Linux 1中国–贵州–贵阳 移动 ip address 117.187.*.*

    我看看你咋弄的 哈哈

    • 似水流年

      IBrowse r IBrowse r Android 12 Android 12 1中国–河南–漯河 联通 ip address 125.44.*.*

      不停的折腾😸

  • acevs

    Google Chrome 131 Google Chrome 131 Windows 10 Windows 10 1中国–山东–青岛 联通 ip address 27.219.*.*

    mark有个印象。

    • 似水流年

      IBrowse r IBrowse r Android 12 Android 12 1中国–河南–漯河 联通 ip address 125.44.*.*

      欢迎mark

  • obaby

    Google Chrome 126 Google Chrome 126 Mac OS X 10.15 Mac OS X 10.15 1中国–山东–青岛 联通 ip address 112.224.*.*

    你把每个站点单独存了啊?我就写到了一个文件里面。

    • 似水流年

      IBrowse r IBrowse r Android 12 Android 12 1中国–河南–漯河 联通 ip address 125.44.*.*

      是的,单独存放了,没有放到一个文件里。本来想着json格式的,但是没成功。

消息盒子
# 您需要首次评论以获取消息 #
# 您需要首次评论以获取消息 #

只显示最新10条未读和已读信息